<?php
namespace Org\Su;
/**
 * Class ConfHelper
 * 配置文件帮助类
 * @since 
 *  1.0 2014-11-14 by sutroon
 *  1.1 2015-1-23 by sutroon 修正[=]等号旁边有空格时候取不到值的问题
 * @example
 * $conf=create_confhelper();
 * $conf->setdir(null,'extension.conf');
 * $conf->section('301');
 * $conf->set('queue','3001');
 * $conf->set('trunk','trunk301');
 * $conf->section('303');
 * $conf->set('queue','3003');
 * $conf->section('302');
 * $conf->set('queue','3002');
 * $conf->comment('queue','这是302-queue注释');
 * $conf->set('trunk','trunk302');
 * $conf->set('callerid','05928888888','301');
 * $conf->delete('trunk','303');
 * $conf->delete_section('301');
 * $conf->save();
 */
class ConfHelper
{
    /**
     * 配置文件目录
     * @var string
     */
    private $conf_dir;

    /**
     * 配置文件具体路径
     * @var string
     */
    private $conf_path;

    /**
     * 配置文件数组
     * @var array
     */
    private $conf_data = false;

    /**
     * 配置内容节点
     * @var string
     */
    private $conf_section;

    /**
     * 是否需要节点
     * @var bool
     */
    private $conf_hasSection = false;

    public function __construct()
    {
        $this->setdir(APP_PATH . 'Runtime/Conf/');
        $this->conf_section = 'default';
    }

    /**
     * 设置配置文件路径
     * @param string $dir 如 ./XCall/Runtime/Conf/或APP_PATH . 'Runtime/Conf/',如果为空字符串则使用上次默认的路径
     * @param string $fileName 配置文件名称 默认 AppConf.conf
     * @param bool $read 是否重新读取数据
     * @since 1.0 2014-11-14 by sutroon
     * @example
     *      setdir(APP_PATH . 'Runtime/Conf/');
     *      setdir(null,'extension.conf');
     *      setdir(null,'extension',false);
     */
    public function setdir($dir, $fileName = 'AppConf.conf', $read = true)
    {
        if ($dir) {
            $this->conf_dir = $dir;
            if (!is_dir($dir)) {
                mkdir($dir, 0777, true);
            }
        }
        $this->conf_path = $this->conf_dir . $fileName;
        if (!$read) {
            return;
        }
        if (!is_file($this->conf_path)) {
            $this->conf_data = false;
            return;
        }
        $conf_str = file_get_contents($this->conf_path);
        $conf_items = explode(PHP_EOL, $conf_str);
        $i = 0;
        $sub_arr = null;
        $section = $this->conf_section;
        $key = null;
        foreach ($conf_items as $item) {
            if (!$item) {
                continue;
            }
            if ($i == 0 && $item[0] !== '[' && !$section) {
                $section = 'default';
            }
            if ($item[0] == '[') {
                if ($sub_arr) {
                    $data[$section] = $sub_arr;
                    unset($sub_arr);
                }
                $section = substr($item, 1, strlen($item) - 2);
                $this->conf_hasSection = true;
                $i++;
                continue;
            }
            if ($item[0] == '#') {
                $comment[] = strlen($item) > 1 ? trim(substr($item, 1)) : '';
                $i++;
                continue;
            }
            if (false !== ($pos = strpos($item, '='))) {
                $key = trim(substr($item, 0, $pos));
                $sub_arr[$key] = ltrim(substr($item, $pos + 1));
                if ($comment) {
                    $sub_arr[$key . '#'] = $comment;
                    unset($comment);
                }
                $i++;
                continue;
            }
            $sub_arr[$item] = false;
            $i++;
        }
        if ($sub_arr) {
            $data[$section] = $sub_arr;
        }
        $this->conf_data = $data ? $data : false;
    }

    /**
     * 检测配置文件是否存在
     * @return bool
     * @since 1.0 2014-11-15 by sutroon
     */
    function exists_file()
    {
        return is_file($this->conf_path);
    }

    /**
     * 设置节点名称
     * @param string $name 节点名称
     * @since 1.0 2014-11-15 by sutroon
     */
    function section($name)
    {
        $this->conf_section = $name;
        $this->conf_hasSection = true;
    }

    /**
     * 获取配置内容的值
     * @param string $name 键名
     * @param string $section 节点名称
     * @return mixed 成功则返回值，否则返回false
     * @since 1.0 2014-11-14 by sutroon
     */
    function get($name, $section = null)
    {
        if (!$section) {
            $section = $this->conf_section;
        }        
        return false === $this->conf_data || !isset($this->conf_data[$section]) || !isset($this->conf_data[$section][$name]) ? false : $this->conf_data[$section][$name];
    }

    /**
     * 修改配置内容
     * @param string $name 键名
     * @param mixed $value 键值
     * @param string $section 节点名称
     * @since 1.0 2014-11-14 by sutroon
     */
    function set($name, $value, $section = null)
    {
        if ($section) {
            $this->conf_hasSection = true;
        } else {
            $section = $this->conf_section;
        }

        $this->conf_data[$section][$name] = $value;
    }

    /**
     * 添加注释
     * @param string $name 键名
     * @param string $comment 注释内容
     * @param string $section 节点名称
     * @since 1.0 2014-11-15 by sutroon
     * @example
     *      section('302');
     *      comment('queue','这是302-queue注释');
     *      comment('queue','这是301-queue注释','301');
     */
    function comment($name, $comment, $section = null)
    {
        if ($section) {
            $this->conf_hasSection = true;
        } else {
            $section = $this->conf_section;
        }
        if (isset($this->conf_data[$section][$name . '#']) && in_array($comment, $this->conf_data[$section][$name . '#'])) {
            return;
        }
        $this->conf_data[$section][$name . '#'][] = $comment;
    }

    /**
     * 删除节点中的元素
     * @param string $name 键名
     * @param string $section 节点名称
     * @since 1.0 2014-11-15 by sutroon
     * @example
     *  delete('queue','302');
     *  section('301');
     *  delete('queue');
     */
    function delete($name, $section = null)
    {
        if (!$section) {
            $section = $this->conf_section;
        }
        if (false !== $this->conf_data && isset($this->conf_data[$section][$name])) {
            unset($this->conf_data[$section][$name]);
        }
    }

    /**
     * 删除整个节点的内容
     * @param string $section
     * @since 1.0 2014-11-15 by sutroon
     * @example delete_section('301');
     */
    function delete_section($section)
    {
        if (false !== $this->conf_data && isset($this->conf_data[$section])) {
            unset($this->conf_data[$section]);
        }
    }

    /**
     * 把配置内容保存到文件中
     * @since 1.0 2014-11-14 by sutroon
     */
    function save()
    {
        if (false === $this->conf_data) {
            return;
        }
        $str = '';
        $data = $this->conf_data;
        $sort_section = array_keys($data);
        sort($sort_section);
        foreach ($sort_section as $section) {
            if ($this->conf_hasSection) {
                $str .= "[$section]" . PHP_EOL;
            }
            $sub = $data[$section];
            if (!$sub) {
                continue;
            }
            $sort_keys = array_keys($sub);
            sort($sort_keys);
            foreach ($sort_keys as $k) {
                if ($k[strlen($k) - 1] == '#') {
                    continue;
                }
                if (isset($sub[$k . '#'])) {
                    $comments = $sub[$k . '#'];
                    foreach ($comments as $comment) {
                        $str .= '# ' . $comment . PHP_EOL;
                    }
                }
                $str .= $k . '=' . $sub[$k] . PHP_EOL;
            }
        }
        file_put_contents($this->conf_path, $str);
    }

    /**
     * 批量保存内容到配置文件
     * @param array $data 数据
     * @param string $section_key 节点字段名
     * @since 1.0 2014-11-15 by sutroon
     * @example batch_save(array(array('userName'=>'u1','trunk'=>'trunk1'),array('userName'=>'u2','trunk'=>'trunk2')),'userName');
     */
    function batch_save($data, $section_key)
    {
        $str = '';
        foreach ($data as $row) {
            foreach ($row as $k => $v) {
                if ($k == $section_key) {
                    $str .= '[' . $v . ']' . PHP_EOL;
                    continue;
                }
                $str .= $k . '=' . $v . PHP_EOL;
            }
        }
        file_put_contents($this->conf_path, $str);
    }

    /**
     * 获取表单
     * @return string
     * @since 1.0 2014-11-18 by sutroon
     */
    function getForm()
    {
        if (!$this->conf_data) {
            return '';
        }
        $str = '';
        $data = $this->conf_data;
        $sort_section = array_keys($data);
        sort($sort_section);
        foreach ($sort_section as $section) {
            if ($this->conf_hasSection) {
                $str .= "<fieldset><legend>$section<input type='hidden' name='section[]' value='$section' size='6' /></legend>";
                $str .= '<table>';
                $str .= '<tr><th>键名</th><th>键值</th></tr>';
            }
            $sub = $data[$section];
            if (!$sub) {
                continue;
            }
            $sort_keys = array_keys($sub);
            sort($sort_keys);
            foreach ($sort_keys as $k) {
                if ($k[strlen($k) - 1] == '#') {
                    continue;
                }
                if (isset($sub[$k . '#'])) {
                    $comments = $sub[$k . '#'];
                    foreach ($comments as $comment) {
                        $str .= '# ' . $comment . PHP_EOL;
                    }
                }
                $str .= '<tr><td><input type="text" name="key' . $section . '[]" value="' . $k . '" size="6" /></td><td><input type="text" name="value' . $section . '[]" value="' . $sub[$k] . '" size="30" /></td></tr>';
            }
            if ($this->conf_hasSection) {
                $str .= '</table>';
                $str .= '</fieldset>';
            }

        }
        return $str;
    }

    /**
     * 保存表单数据到配置文件
     * @since 1.0 2014-11-18 by sutroon
     */
    function saveForm()
    {
        $str = '';
        $sections = I('section');
        foreach ($sections as $section) {
            $str .= "[$section]" . PHP_EOL;
            $keys = I('key' . $section);
            $values = I('value' . $section);
            $i = 0;
            foreach ($keys as $key) {
                $str .= $key . '=' . $values[$i] . PHP_EOL;
                $i++;
            }
        }
        file_put_contents($this->conf_path, $str);
    }
}